#-
# ==========================================================================
# Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
# rights reserved.
#
# The coded instructions, statements, computer programs, and/or related 
# material (collectively the "Data") in these files contain unpublished 
# information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
# licensors, which is protected by U.S. and Canadian federal copyright 
# law and by international treaties.
#
# The Data is provided for use exclusively by You. You have the right 
# to use, modify, and incorporate this Data into other products for 
# purposes authorized by the Autodesk software license agreement, 
# without fee.
#
# The copyright notices in the Software and this entire statement, 
# including the above license grant, this restriction and the 
# following disclaimer, must be included in all copies of the 
# Software, in whole or in part, and all derivative works of 
# the Software, unless such copies or derivative works are solely 
# in the form of machine-executable object code generated by a 
# source language processor.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
# AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
# WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
# NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
# PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
# TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
# BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
# DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
# AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
# OR PROBABILITY OF SUCH DAMAGES.
#
# ==========================================================================
#+

#
#	Creation Date:   27 September 2006
#
#	Description:
#
#		Traces the position of an animated object
#		and create a curve showing the object's path.
#
#	Usage:
#
#		Animate an object.
#		Select the object.
#		Run the command in the command window.
#		See the object's path drawn as a curve.
#
#	Options:
#
#		s=<frame>		The start frame.  Default to 1.
#		e=<frame>		The end frame.	Default to 60.
#		b=<frame>		The by frame.  Default to 1.
#
#	Example:
#
#		From Python:
#			import maya
#			maya.cmds.spMotionTrace(s=1, e=100, b=2)
#
#		From Mel:
#			spMotionTrace -s 1 -e 100 -b 2
#

import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import math, sys

kPluginCmdName="spMotionTrace"

kStartFlag = "-s"
kStartLongFlag = "-startFrame"
kEndFlag = "-e"
kEndLongFlag = "-endFrame"
kByFlag = "-b"
kByLongFlag = "-byFrame"

# command
class motionTrace(OpenMayaMPx.MPxCommand):
	def __init__(self):
		OpenMayaMPx.MPxCommand.__init__(self)
		# setup private data members
		self.__start = 1
		self.__end = 60
		self.__by = 1


	def doIt(self, args):
		"""
		This method is called from script when this command is called.
		It should set up any class data necessary for redo/undo,
		parse any given arguments, and then call redoIt.
		"""
		argData = OpenMaya.MArgDatabase(self.syntax(), args)

		if argData.isFlagSet(kStartFlag):
			self.__start = argData.flagArgumentInt(kStartFlag, 0)
		if argData.isFlagSet(kEndFlag):
			self.__end = argData.flagArgumentInt(kEndFlag, 0)
		if argData.isFlagSet(kByFlag):
			self.__by = argData.flagArgumentInt(kByFlag, 0)

		self.redoIt()


	def redoIt(self):
		"""
		This method performs the action of the command.
		This method iterates over all selected items and
		prints out connected plug and dependency node type
		information.
		"""
		picked = OpenMaya.MObjectArray()
		dependNode = OpenMaya.MObject()     # Selected dependency node

		# Create a selection list iterator
		slist = OpenMaya.MSelectionList()
		OpenMaya.MGlobal.getActiveSelectionList(slist)
		iter = OpenMaya.MItSelectionList(slist)

		# Iterate over all selected dependency nodes
		# and save them in a list
		while not iter.isDone():
			# Get the selected dependency node
			iter.getDependNode(dependNode)
			picked.append(dependNode)
			iter.next()

		# sample the animation using start, end, by values
		pointArrays = [ OpenMaya.MPointArray() for i in range(picked.length()) ]

		time = self.__start
		while (time <= self.__end):
			timeval = OpenMaya.MTime(time)
			OpenMaya.MGlobal.viewFrame(timeval)

			# Iterate over selected dependency nodes
			for i in range(picked.length()):
				# Get the selected dependency node
				dependNode = picked[i]

				# Create a function set for the dependency node
				fnDependNode = OpenMaya.MFnDependencyNode(dependNode)

				# Get the translation attribute values
				txAttr = fnDependNode.attribute("translateX")
				txPlug = OpenMaya.MPlug(dependNode, txAttr)
				tx = txPlug.asDouble()

				tyAttr = fnDependNode.attribute("translateY")
				tyPlug = OpenMaya.MPlug(dependNode, tyAttr)
				ty = tyPlug.asDouble()

				tzAttr = fnDependNode.attribute("translateZ")
				tzPlug = OpenMaya.MPlug(dependNode, tzAttr)
				tz = tzPlug.asDouble()

				print "adding", tx, ty, tz, "\n"
				pointArrays[i].append(OpenMaya.MPoint(tx, ty, tz))

			time += self.__by

		# make a path curve for each selected object
		for i in range(picked.length()):
			self.__jMakeCurve(pointArrays[i])


	def __jMakeCurve(self, cvs):
		"""
		Make a degree 1 curve from the given CVs.
		
		Note that in Python, a double underscore in front of a member name
		make the method "private" to the class through name-mangling
		"""
		deg = 1
		knots = OpenMaya.MDoubleArray()

		for i in range(cvs.length()):
			knots.append(i)

		# Now create the curve
		nullObj = OpenMaya.MObject()
		curveFn = OpenMaya.MFnNurbsCurve()
		curveFn.create(cvs, knots, deg, OpenMaya.MFnNurbsCurve.kOpen, False, False, nullObj)


# Creator
def cmdCreator():
	return OpenMayaMPx.asMPxPtr(motionTrace())


# Syntax creator
def syntaxCreator():
	syntax = OpenMaya.MSyntax()
	syntax.addFlag(kStartFlag, kStartLongFlag, OpenMaya.MSyntax.kLong)
	syntax.addFlag(kEndFlag, kEndLongFlag, OpenMaya.MSyntax.kLong)
	syntax.addFlag(kByFlag, kByLongFlag, OpenMaya.MSyntax.kLong)
	return syntax


# Initialize the script plug-in
def initializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
	try:
		mplugin.registerCommand(kPluginCmdName, cmdCreator, syntaxCreator)
	except:
		sys.stderr.write("Failed to register command: %s\n" % kPluginCmdName)
		raise


# Uninitialize the script plug-in
def uninitializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.deregisterCommand(kPluginCmdName)
	except:
		sys.stderr.write("Failed to unregister command: %s\n" % kPluginCmdName)
		raise


